home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / pctv3n2.zip / L3.CPP < prev    next >
Text File  |  1992-03-21  |  6KB  |  161 lines

  1. /* cellmap class definition, constructor, copy_cells(), set_cell(),
  2.    clear_cell(), cell_state(), count_neighbors(), and
  3.    next_generation() for fast, hard-wired neighbor count approach.
  4.    Otherwise, the same as Listing 1. */
  5.  
  6. class cellmap {
  7. private:
  8.    unsigned char *cells;
  9.    unsigned int width;
  10.    unsigned int width_in_bytes;
  11.    unsigned int height;
  12.    unsigned int length_in_bytes;
  13. public:
  14.    cellmap(unsigned int h, unsigned int v);
  15.    ~cellmap(void);
  16.    void copy_cells(cellmap &sourcemap);
  17.    void set_cell(unsigned int x, unsigned int y);
  18.    void clear_cell(unsigned int x, unsigned int y);
  19.    int cell_state(int x, int y);
  20.    int count_neighbors(int x, int y);
  21.    void next_generation(cellmap& dest_map);
  22. };
  23.  
  24. /* cellmap constructor. Pads around cell storage area with 1 extra
  25.    byte, used for handling edge wrapping. */
  26. cellmap::cellmap(unsigned int h, unsigned int w)
  27. {
  28.    width = w;
  29.    width_in_bytes = ((w + 7) / 8) + 2; // pad each side with
  30.                                           // 1 extra byte
  31.    height = h;
  32.    length_in_bytes = width_in_bytes * (h + 2); // pad top/bottom
  33.                                           // with 1 extra byte
  34.    cells = new unsigned char[length_in_bytes];  // cell storage
  35.    memset(cells, 0, length_in_bytes);  // clear all cells, to start
  36. }
  37.  
  38. /* Copies one cellmap's cells to another cellmap. If wrapping is
  39.    enabled, copies edge (wrap) bytes into opposite padding bytes in
  40.    source first, so that the padding bytes off each edge have the
  41.    same values as would be found by wrapping around to the opposite
  42.    edge. Both cellmaps are assumed to be the same size. */
  43. void cellmap::copy_cells(cellmap &sourcemap)
  44. {
  45.    unsigned char *cell_ptr;
  46.    int i;
  47.  
  48. #if WRAP_EDGES
  49.    // Copy left and right edges into padding bytes on right and left
  50.    cell_ptr = sourcemap.cells + width_in_bytes;
  51.    for (i=0; i<height; i++) {
  52.       *cell_ptr = *(cell_ptr + width_in_bytes - 2);
  53.       *(cell_ptr + width_in_bytes - 1) = *(cell_ptr + 1);
  54.       cell_ptr += width_in_bytes;
  55.    }
  56.    // Copy top and bottom edges into padding bytes on bottom and top
  57.    memcpy(sourcemap.cells, sourcemap.cells + length_in_bytes -
  58.          (width_in_bytes * 2), width_in_bytes);
  59.    memcpy(sourcemap.cells + length_in_bytes - width_in_bytes,
  60.          sourcemap.cells + width_in_bytes, width_in_bytes);
  61. #endif
  62.    // Copy all cells to the destination
  63.    memcpy(cells, sourcemap.cells, length_in_bytes);
  64. }
  65.  
  66. /* Turns cell on. x and y are offset by 1 byte down and to the right,
  67.    to compensate for the padding bytes around the cell map. */
  68. void cellmap::set_cell(unsigned int x, unsigned int y)
  69. {
  70.    unsigned char *cell_ptr =
  71.          cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
  72.  
  73.    *(cell_ptr) |= 0x80 >> (x & 0x07);
  74. }
  75.  
  76. /* Turns cell off. x and y are offset by 1 byte down and to the right,
  77.    to compensate for the padding bytes around the cell map. */
  78. void cellmap::clear_cell(unsigned int x, unsigned int y)
  79. {
  80.    unsigned char *cell_ptr =
  81.          cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
  82.  
  83.    *(cell_ptr) &= ~(0x80 >> (x & 0x07));
  84. }
  85.  
  86. /* Returns cell state (1=on or 0=off). x and y are offset by 1 byte
  87.    down and to the right, to compensate for the padding bytes around
  88.    the cell map. */
  89. int cellmap::cell_state(int x, int y)
  90. {
  91.    unsigned char *cell_ptr =
  92.          cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
  93.  
  94.    return (*cell_ptr & (0x80 >> (x & 0x07))) ? 1 : 0;
  95. }
  96.  
  97. /* Counts the number of neighboring on-cells for specified cell. */
  98. int cellmap::count_neighbors(int x, int y)
  99. {
  100.    unsigned char *cell_ptr, mask;
  101.    unsigned int neighbor_count;
  102.  
  103.    // Point to upper left neighbor
  104.    cell_ptr = cells + ((y * width_in_bytes) + ((x + 7) / 8));
  105.    mask = 0x80 >> ((x - 1) & 0x07);
  106.    // Count upper left neighbor
  107.    neighbor_count = (*cell_ptr & mask) ? 1 : 0;
  108.    // Count left neighbor
  109.    if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
  110.    // Count lower left neighbor
  111.    if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
  112.  
  113.    // Point to upper neighbor
  114.    if ((mask >>= 1) == 0) {
  115.       mask = 0x80;
  116.       cell_ptr++;
  117.    }
  118.    // Count upper neighbor
  119.    if ((*cell_ptr & mask)) neighbor_count++;
  120.    // Count lower neighbor
  121.    if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
  122.  
  123.    // Point to upper right neighbor
  124.    if ((mask >>= 1) == 0) {
  125.       mask = 0x80;
  126.       cell_ptr++;
  127.    }
  128.    // Count upper right neighbor
  129.    if ((*cell_ptr & mask)) neighbor_count++;
  130.    // Count right neighbor
  131.    if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
  132.    // Count lower right neighbor
  133.    if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
  134.  
  135.    return neighbor_count;
  136. }
  137.  
  138. /* Calculates the next generation of current_map and stores it in
  139.    next_map. */
  140. void cellmap::next_generation(cellmap& next_map)
  141. {
  142.    unsigned int x, y, neighbor_count;
  143.  
  144.    for (y=0; y<height; y++) {
  145.       for (x=0; x<width; x++) {
  146.          neighbor_count = count_neighbors(x, y);
  147.          if (cell_state(x, y) == 1) {
  148.             if ((neighbor_count != 2) && (neighbor_count != 3)) {
  149.                next_map.clear_cell(x, y);    // turn it off
  150.                draw_pixel(x, y, OFF_COLOR);
  151.             }
  152.          } else {
  153.             if (neighbor_count == 3) {
  154.                next_map.set_cell(x, y);      // turn it on
  155.                draw_pixel(x, y, ON_COLOR);
  156.             }
  157.          }
  158.       }
  159.    }
  160. }
  161.